/*************************************************************************
	> File Name: dasserver.cpp
	> Author: xuwenlong
	> Mail: myxuan475@126.com 
	> Created Time: 2018年09月17日 星期一 14时00分18秒
 ************************************************************************/
#include <iostream>
#include <sys/select.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include <string.h>
#include <event.h>
#include <stdlib.h>
#include <event2/rpc.h>
#include <event2/listener.h>
#include <event2/thread.h>

#include <dirent.h>
#include "dasclient.h"
#include "clienthandler.h"
#include <utils/logger.h>
#include <utils/config.h>
#include <dirent.h>
#include <sys/stat.h>
#include <dbms/status.h>
#include <time.h>

DasClient::DasClient():
    Sclient(new ClientHandler(this),true),
    m_pTimer(new Timer("dasclient",this)),
    m_iwait(0)
{
    m_pTimer->Start(15000,kPeriodic);
}

DasClient::~DasClient()
{
    ExitLoop();
    m_pTimer->Stop();
    delete m_pTimer;
}

void DasClient::RunTimer()
{
    std::string ipAddr =
            utils::GetConfigFileStringValue("Config.ini","BASE","center","127.0.0.1");
    int port = utils::GetConfigFileIntValue("Config.ini","BASE","port",9797);
    RunLoop(ipAddr.c_str(),"47.111.163.44",port);
}

void DasClient::OnStatus(bool connect)
{
    LOG_DEBUG("Network changed:%d",(int)connect);
    for (U32 task = 0;
         task < DAS_TASK_MAX;task++) {
        ModuleInterface *bi = (ModuleInterface*)GetTask((DAS_TASK)task);
        if (bi) {
            bi->RedoNetwork(connect);
        }
    }
}

BOOL DasClient::OnReceiveJson(S32 index,DAS_RESULT status, const string &method, const Json::Value &result)
{
    if (method == "uploadFile") {
        if (status != DAS_SUCCESS) {
//            stopClient();// 上传超时
            return TRUE;
        }

        AutoLock aulock(m_uploadlock);
        int upload = result.asInt();
        m_seek +=upload;
        m_uploadlen = 0;
        char file[MAX_NAME_LEN];

        sprintf(file,"%s/log/%s",
                getenv(CONFIG_DIR_ENV),
                m_filename.c_str());

        FILE *fd = fopen(file,"r");
        if (!fd) {
            remove(file);
            return TRUE;
        }
        fseek(fd,0,SEEK_END);
        long filelen = ftell(fd);
        fclose(fd);
        if (m_seek >= filelen) {
            remove(file);
            m_filename = "";
            m_seek = 0;
        }
        return TRUE;
    }
    else
        return Sclient::OnReceiveJson(index,status,method,result);
}

void DasClient::TimeoutEvent()
{
    //每70分钟上报一次
//    m_iwait = 280;
    if (m_iwait++ >= 280) {
        m_iwait = 0;
        reportError();
    }
    char path[MAX_NAME_LEN];

    sprintf(path,"%s/log",getenv(CONFIG_DIR_ENV));

    AutoLock aulock(m_uploadlock);
    if (m_filename.empty()) {
        m_seek = 0;
        m_uploadlen = 0;
        m_filename = utils::logFileNotoday(path);
    }

    if (!m_filename.empty()) {
        char file[MAX_NAME_LEN];

        sprintf(file,"%s/%s",path,m_filename.c_str());
        FILE *fd = fopen(file,"r");
        if (!fd) {
            remove(file);
            m_filename = "";
            return;
        }
        fseek(fd, 0, SEEK_END);
        long filelen = ftell(fd);
        long length = filelen - m_seek;

        if (length <= 0) {
            remove(file);
            m_filename = "";
            return;
        }

        if (length >= MAX_FILE_SIZE) {
            m_uploadlen = MAX_FILE_SIZE;
        }
        else
            m_uploadlen = length;

        char *src = (char*)malloc(m_uploadlen+1);

        fseek(fd,m_seek,SEEK_SET);
        fread(src,m_uploadlen,1,fd);
        src[m_uploadlen] = 0;
        fclose(fd);

        Json::Value params;
        params["name"] = m_filename;
        params["content"] = src;
        params["seek"] = m_seek;

        int id = m_pProtocolHandler->SendJsonRpc(
                    this,"uploadFile",params,15);
        if (-1 == id) {
            stopClient();
        }
        free(src);
    }
    else {
        Sclient::TimeoutEvent();
    }
}

void DasClient::reportError()
{
    map<int,FileStruct> filelist;
    fileList(filelist);

    U64  acq_last = 0;
    U64  up_last = 0;
    int  up_fail = 0;
    int acq_fail = 0;

    time_t now = time(NULL);
    for (map<int,FileStruct>::iterator iter = filelist.begin();
         iter != filelist.end();iter++) {
        int id = iter->first;
        FileStruct &file = iter->second;

        //采集状态

        U64 last = (U64)difftime(now,file.last_status);
        if (!file.status)
            acq_fail++;
        else {
            if (last > 70*60)
                acq_fail++;
        }
        if ((acq_last == 0 || last < acq_last) && (last > 4200 || (!file.status)))
            acq_last = last;
        //上传状态

        last = (U64)difftime(now, file.last_data);

        if (last > 4200 && file.leftdata > 0) {
            up_fail += file.leftdata;

            if (up_last == 0 || last < up_last) {
                up_last = last;
            }
        }
    }

    Json::Value params;
    params["count"] = filelist.size();
    params["acqlast"] = acq_last;
    params["acqfail"] = acq_fail;
    params["uplast"] = up_last;
    params["upfail"] = up_fail;

    int id = m_pProtocolHandler->SendJsonRpc(
                this,"reportError",params,30);
    if (-1 == id) {
        stopClient();
    }
}

int DasClient::fileList(map<int,DasClient::FileStruct> &filelist)
{
    DIR *pdir;
    struct dirent *pdirent;
    char path[256];

    sprintf(path,"%s/data",getenv(CONFIG_DIR_ENV));
    pdir = opendir(path);

    if (pdir == NULL)
        return 0;
    for (pdirent = readdir(pdir);pdirent != NULL;pdirent = readdir(pdir)) {
        if (strcmp(pdirent->d_name,".") == 0 ||
                strcmp(pdirent->d_name,"..") == 0)
            continue;
        if (pdirent->d_type != 8)
            continue;

        char fullname[256] = {0};
        int  id = 0;
        sprintf(fullname,"%s/%s",path,pdirent->d_name);
        id = fileId(pdirent->d_name);

        if (id == 0)
            continue;
        map<int,FileStruct>::iterator iter;
        FileStruct sfile = {0};
        if ((iter = filelist.find(id)) != filelist.end()) {
            sfile = iter->second;
        }

        if (strstr(pdirent->d_name,"STATUS")) {

            struct stat fstat;
            if (0 == (sfile.success = stat(fullname,&fstat))) {
                sfile.last_status = fstat.st_mtime;
                status sta(id);
                sfile.status = sta.istatus();
            }
            filelist[id] = sfile;
        }
        else if (strstr(pdirent->d_name,"LIST")) {
            struct stat fstat;
            if (0 == (sfile.success = stat(fullname,&fstat))) {
                sfile.last_data = fstat.st_mtime;
                sfile.leftdata = fstat.st_size/20;//数据个数
            }
            filelist[id] = sfile;
        }
    }
    closedir(pdir);
    return filelist.size();
}

int DasClient::fileId(const char *filename)
{
    int  id = 0;
    const char *strId = NULL;
    if (strstr(filename,"STATUS")) {
        strId = &filename[6];
        id = atoi(strId);
    }
    else if (strstr(filename,"LIST")) {
        strId = &filename[4];
        id = atoi(strId);
    }
    return id;
}
